var SCRIBEFIRE_DB = {
	db : null,
	inBatch : false,
	
	dbStack : 0,
	
	notesTable : "notes_v1",
	templatesTable : "blog_templates",
	stateTable : "state_v1",
	historyTable : "history_v1",
	blogsTable : "blogs_v1",
	
	dbFile : null,
	timer : null,
	
	get prefs() { return Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch("performancing."); },
	
	load : function () {
		var db = this.getDB();
		
		if (!db.tableExists(this.templatesTable)) {
			db.executeSimpleSQL("CREATE TABLE "+this.templatesTable+" (blog_guid TEXT PRIMARY KEY, template TEXT, date INTEGER, live_preview INTEGER DEFAULT 1)");
		}
		
		if (!db.tableExists(this.notesTable)) {
			db.executeSimpleSQL("CREATE TABLE "+this.notesTable+" (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, content TEXT, modified INTEGER)");
		}
		
		if (!db.tableExists(this.stateTable)) {
			db.executeSimpleSQL("CREATE TABLE "+this.stateTable+" (id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT, entryId TEXT, originalDateCreated TEXT, content TEXT, title TEXT, tags TEXT, categories TEXT, isDraft INTEGER DEFAULT 0)");
		}
		
		if (!db.tableExists(this.historyTable)) {
			db.executeSimpleSQL("CREATE TABLE "+this.historyTable+" (id INTEGER PRIMARY KEY AUTOINCREMENT, blogId INTEGER DEFAULT 0, postId TEXT, content TEXT, title TEXT, categories TEXT, dateCreated INTEGER, tags TEXT, isDraft INTEGER DEFAULT 0, type TEXT DEFAULT 'post', slug TEXT)");
		}
		else {
		    try {
		        db.executeSimpleSQL("ALTER TABLE "+this.historyTable+" ADD slug TEXT");
	        } catch (e) {
            }
	    }
		
		if (!db.tableExists(this.blogsTable)) {
			db.executeSimpleSQL("CREATE TABLE "+this.blogsTable+" (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, type TEXT, api TEXT, key TEXT, username TEXT, guid TEXT, url TEXT, blogId TEXT, useBoolean TEXT, ftp_username TEXT, ftp_host TEXT, ftp_protocol TEXT, ftp_path TEXT, ftp_url_to_path TEXT)");
		}
		else {
		    try {
		        db.executeSimpleSQL("DELETE FROM blogs_v1 WHERE type='s_myspace' OR type='myspace_com'");
		    } catch (e) {
	        }
		    
			try {
			    db.executeSimpleSQL("ALTER TABLE blogs_v1 ADD ftp_username TEXT");
                db.executeSimpleSQL("ALTER TABLE blogs_v1 ADD ftp_protocol TEXT");
                db.executeSimpleSQL("ALTER TABLE blogs_v1 ADD ftp_path TEXT");
                db.executeSimpleSQL("ALTER TABLE blogs_v1 ADD ftp_url_to_path TEXT");
                db.executeSimpleSQL("ALTER TABLE blogs_v1 ADD ftp_host TEXT");
		        
			    // Copy over the FTP settings.
			    
                try {
                    var ftp_username = this.prefs.getCharPref('ftp.username');
                    var ftp_host = this.prefs.getCharPref('ftp.host');
                    var ftp_path = this.prefs.getCharPref('ftp.path');
                    var ftp_url_to_path = this.prefs.getCharPref('ftp.url-to-path');
                    var ftp_protocol = this.prefs.getCharPref('ftp.protocol');
                    
    			    var update = db.createStatement("UPDATE blogs_v1 SET ftp_username=?1, ftp_host=?2, ftp_protocol=?3, ftp_path=?4, ftp_url_to_path=?5");
    			    update.bindUTF8StringParameter(0, ftp_username);
    			    update.bindUTF8StringParameter(1, ftp_host);
    			    update.bindUTF8StringParameter(2, ftp_protocol);
    			    update.bindUTF8StringParameter(3, ftp_path);
    			    update.bindUTF8StringParameter(4, ftp_url_to_path);
    			    update.execute();
    			    update.finalize();
                } catch (e) {
                }
		    } catch (e) {
	        }
	        
	        
		}
		
		this.closeDB(db);
	},
	
	getDB : function () {
		this.dbStack++;
		
		if (this.dbStack > 1) {
			return this.db;
		}
		
		var storageService = Components.classes["@mozilla.org/storage/service;1"]
		                        .getService(Components.interfaces.mozIStorageService);
		
		if (!this.dbFile) {
			this.dbFile = Components.classes["@mozilla.org/file/directory_service;1"]
			                     .getService(Components.interfaces.nsIProperties)
			                     .get("ProfD", Components.interfaces.nsIFile);
			this.dbFile.append("scribefire.sqlite");
		}
		
		try {
			this.db = storageService.openDatabase(this.dbFile);
		} catch (e) {
			// Corrupt or non-SQLite file.
			// TODO Remove/recreate file.
			throw e;
		}
		
		return this.db;
	},
	
	closeDB : function (foo, force) {
		this.dbStack--;
		
		if (force) this.dbStack = 0;
	
		if (this.dbStack == 0) {
			try { this.db.close(); } catch (e) { }
		}
	},
	
	getBlogTemplate : function (blog_guid) {
		var db = this.getDB();
		var select = db.createStatement("SELECT template FROM "+SCRIBEFIRE_DB.templatesTable+" WHERE blog_guid=?1");
		select.bindStringParameter(0, blog_guid);
		
		var template = "";
		
		try {
			while (select.executeStep()) {
				template = select.getString(0);
				break;
			}
		} catch (e) {
		} finally {
			select.reset();
		}
		
		this.closeDB(db);
		
		return template;
	},
	
	saveBlogTemplate : function (blog_guid, template, live_preview) {
		var db = this.getDB();
		
		if (live_preview) live_preview = 1;
		else live_preview = 0;
		
		var insert = db.createStatement("INSERT INTO blog_templates (blog_guid, template, date, live_preview) VALUES (?1, ?2, ?3, ?4)");
		insert.bindUTF8StringParameter(0, blog_guid);
		insert.bindUTF8StringParameter(1, template);
		insert.bindInt64Parameter(2, (new Date().getTime()));
		insert.bindInt64Parameter(3, live_preview);
		
		try { insert.execute(); } catch (duplicateKey) {
			var update = db.createStatement("UPDATE blog_templates SET template=?1, date=?2 WHERE blog_guid=?3");
			update.bindUTF8StringParameter(0, template);
			update.bindInt64Parameter(1, (new Date().getTime()));
			update.bindUTF8StringParameter(2, blog_guid);
			
			try { update.execute(); } catch (e) { }
			update.finalize();
		}
		
		insert.finalize();
		
		this.closeDB(db);
	},
	
	deleteBlogTemplate : function (blog_guid) {
		var db = this.getDB();
		var deleter = db.createStatement("DELETE FROM blog_templates WHERE blog_guid=?1");
		deleter.bindUTF8StringParameter(0, blog_guid);
		deleter.execute();
		this.closeDB(db);
	},
	
	export : function () {
		this.load();
		
        var nsIFilePicker = Components.interfaces.nsIFilePicker;
        var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
        fp.defaultString = "scribefire_backup.sqlite"
        fp.init(window, null, nsIFilePicker.modeSave);
        
        var rv = fp.show();

        if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
            var target_file = fp.file;
            
            var source_file = Components.classes["@mozilla.org/file/directory_service;1"]
			                     .getService(Components.interfaces.nsIProperties)
			                     .get("ProfD", Components.interfaces.nsIFile);
			source_file.append("scribefire.sqlite");
            
            var ios = Components.classes["@mozilla.org/network/io-service;1"].
                                getService(Components.interfaces.nsIIOService);
            var url = ios.newFileURI(source_file, null, null);

            var pngFile = url.QueryInterface(Components.interfaces.nsIFileURL).file;
            var istream = Components.classes["@mozilla.org/network/file-input-stream;1"].
                                    createInstance(Components.interfaces.nsIFileInputStream);
            istream.init(pngFile, -1, -1, false);

            var bstream = Components.classes["@mozilla.org/binaryinputstream;1"].
                                    createInstance(Components.interfaces.nsIBinaryInputStream);
            bstream.setInputStream(istream);

            var bytes = bstream.readBytes(bstream.available());

            var aFile = target_file;

            var stream = Components.classes["@mozilla.org/network/safe-file-output-stream;1"].
                                   createInstance(Components.interfaces.nsIFileOutputStream);
            stream.init(aFile, 0x04 | 0x08 | 0x20, 0600, 0); // write, create, truncate

            stream.write(bytes, bytes.length);
            
            if (stream instanceof Components.interfaces.nsISafeOutputStream) {
                stream.finish();
            } else {
                stream.close();
            }
            
            var dbFile = fp.file.parent;
            dbFile.append(fp.file.leafName);
            
            try {
                var storageService = Components.classes["@mozilla.org/storage/service;1"]
        		                        .getService(Components.interfaces.mozIStorageService);
        		var db = storageService.openDatabase(dbFile);
                
                db.executeSimpleSQL("DROP TABLE history_v1");
                db.executeSimpleSQL("DROP TABLE state_v1");
                
                if (!db.tableExists("prefs")) {
        		    db.executeSimpleSQL("CREATE TABLE prefs (name TEXT, type TEXT, value TEXT)");
        	    }
                
                var children = this.prefs.getChildList("", {});
                
                for (var i = 0; i < children.length; i++) {
                    var pref_name = children[i];
                    var pref_type = "";
                    var pref_value = "";
                
                
                    switch (this.prefs.getPrefType(children[i])) {
                        case this.prefs.PREF_STRING:
                            pref_type = "string";
                            pref_value = this.prefs.getComplexValue(pref_name, Components.interfaces.nsISupportsString).data;
                        break;
                        case this.prefs.PREF_INT:
                            pref_type = "int";
                            pref_value = this.prefs.getIntPref(pref_name);
                        break;
                        case this.prefs.PREF_BOOL:
                            pref_type = "bool";
                            pref_value = this.prefs.getBoolPref(pref_name);
                        break;
                        case this.prefs.PREF_INVALID:
                            continue;
                        break;
                    }
                
                    var insert = db.createStatement("INSERT INTO prefs (name, type, value) VALUES (?1, ?2, ?3)");
                    insert.bindUTF8StringParameter(0, pref_name);
                    insert.bindUTF8StringParameter(1, pref_type);
                    insert.bindUTF8StringParameter(2, pref_value);
                    insert.execute();
                    insert.finalize();
                }
            } catch (e) {
                alert("Error exporting prefs:\n\n" + e);
            }
        }
    },
    
    import : function () {
		this.load();
		
        var nsIFilePicker = Components.interfaces.nsIFilePicker;
        var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
        fp.appendFilter("SQLite Files","*.sqlite");
        
        fp.init(window, null, nsIFilePicker.modeOpen);
        
        var rv = fp.show();

        if (rv == nsIFilePicker.returnOK) {
    		var storageService = Components.classes["@mozilla.org/storage/service;1"]
    		                        .getService(Components.interfaces.mozIStorageService);
    		var db = storageService.openDatabase(fp.file);
    		var sf_db = SCRIBEFIRE_DB.getDB();
    		
    		try {
        		// Blogs
        		var select = db.createStatement("SELECT name, type, api, key, username, guid, url, blogId, useBoolean, ftp_username, ftp_host, ftp_protocol, ftp_path, ftp_url_to_path FROM blogs_v1");

        		try {
        			while (select.executeStep()) {
        			    var guid = select.getUTF8String(5);
    			    
        			    // Check if a blog with guid already exists in our DB
        			    var check = sf_db.createStatement("SELECT id FROM blogs_v1 WHERE guid=?1");
        			    check.bindUTF8StringParameter(0, guid);
    			    
        			    var exists = false;
    			    
        			    try {
        			        while (check.executeStep()) {
        			            exists = true;
    			            
        			            var update = sf_db.createStatement("UPDATE blogs_v1 SET name=?1, type=?2, api=?3, key=?4, username=?5, url=?6, blogId=?7, useBoolean=?8, ftp_username=?10, ftp_host=?11, ftp_protocol=?12, ftp_path=?13, ftp_url_to_path=?14 WHERE guid=?9");
        			            update.bindUTF8StringParameter(0, select.getUTF8String(0));
        			            update.bindUTF8StringParameter(1, select.getUTF8String(1));
        			            update.bindUTF8StringParameter(2, select.getUTF8String(2));
        			            update.bindUTF8StringParameter(3, select.getUTF8String(3));
        			            update.bindUTF8StringParameter(4, select.getUTF8String(4));
        			            update.bindUTF8StringParameter(5, select.getUTF8String(6));
        			            update.bindUTF8StringParameter(6, select.getUTF8String(7));
        			            update.bindUTF8StringParameter(7, select.getUTF8String(8));
        			            update.bindUTF8StringParameter(8, guid);
        			            update.bindUTF8StringParameter(9, select.getUTF8String(9));
                                update.bindUTF8StringParameter(10, select.getUTF8String(10));
                                update.bindUTF8StringParameter(11, select.getUTF8String(11));
                                update.bindUTF8StringParameter(12, select.getUTF8String(12));
                                update.bindUTF8StringParameter(13, select.getUTF8String(13));
    			            
        			            update.execute();
    			                update.finalize();
    			                
        			            break;
    			            }
    			        } catch (e) {
    		            } finally {
    		                check.reset();
    	                }
	                
    	                if (!exists) {
    	                    var insert = sf_db.createStatement("INSERT INTO blogs_v1 (name, type, api, key, username, guid, url, blogId, useBoolean, ftp_username, ftp_host, ftp_protocol, ftp_path, ftp_url_to_path) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14)");
    	                    insert.bindUTF8StringParameter(0, select.getUTF8String(0));
    			            insert.bindUTF8StringParameter(1, select.getUTF8String(1));
    			            insert.bindUTF8StringParameter(2, select.getUTF8String(2));
    			            insert.bindUTF8StringParameter(3, select.getUTF8String(3));
    			            insert.bindUTF8StringParameter(4, select.getUTF8String(4));
    			            insert.bindUTF8StringParameter(5, select.getUTF8String(5));
    			            insert.bindUTF8StringParameter(6, select.getUTF8String(6));
    			            insert.bindUTF8StringParameter(7, select.getUTF8String(7));
    			            insert.bindUTF8StringParameter(8, select.getUTF8String(8));
    			            insert.bindUTF8StringParameter(9, select.getUTF8String(9));
    			            insert.bindUTF8StringParameter(10, select.getUTF8String(10));
    			            insert.bindUTF8StringParameter(11, select.getUTF8String(11));
    			            insert.bindUTF8StringParameter(12, select.getUTF8String(12));
    			            insert.bindUTF8StringParameter(13, select.getUTF8String(13));
			            
    			            insert.execute();
    			            insert.finalize();
                        }
        			}
        		} catch (e) {
        		} finally {
        			select.reset();
        		}
                
                this.execFunction(
                    function (win) {
                        win.performancingUI.reLoadBlogs();
                    }
                );
            } catch (e) {
                alert("Error importing blogs:\n\n" + e);
            }
            
            try {
                // Notes
        		var select = db.createStatement("SELECT title, content, modified FROM notes_v1");

        		try {
        			while (select.executeStep()) {
        			    var title = select.getUTF8String(0);
        			    var content = select.getUTF8String(1);
        			    var modified = select.getInt64(2);
    			    
        			    // Check if this note already exists.
        			    var check = sf_db.createStatement("SELECT id FROM notes_v1 WHERE (title=?1 AND content=?2)");
        			    check.bindUTF8StringParameter(0, title);
                        check.bindUTF8StringParameter(1, content);
                    
        			    var exists = false;
    			    
        			    try {
        			        while (check.executeStep()) {
        			            exists = true;
        			            break;
    			            }
    			        } catch (e) {
    		            } finally {
    		                check.reset();
    	                }
	                
    	                if (!exists) {
    	                    var insert = sf_db.createStatement("INSERT INTO notes_v1 (title, content, modified) VALUES (?1, ?2, ?3)");
    	                    insert.bindUTF8StringParameter(0, title);
    	                    insert.bindUTF8StringParameter(1, content);
    	                    insert.bindInt64Parameter(2, modified);
	                    
    			            insert.execute();
    			            insert.finalize();
                        }
        			}
        		} catch (e) {
        		} finally {
        			select.reset();
        		}
    		
        		// Reload notes.
        		
                this.execFunction(
                    function (win) {
                        win.SCRIBEFIRE_NOTES.loadNotes();
                    }
                );
            } catch (e) {
                alert("Error importing notes:\n\n" + e);
            }
            
            try {
        		var select = db.createStatement("SELECT blog_guid, template, date, live_preview FROM blog_templates");

        		try {
        			while (select.executeStep()) {
        			    var guid = select.getUTF8String(0);
    			    
        			    // Check if a blog with guid already exists in our DB
        			    var check = sf_db.createStatement("SELECT blog_guid FROM blog_templates WHERE blog_guid=?1");
        			    check.bindUTF8StringParameter(0, guid);
    			    
        			    var exists = false;
    			    
        			    try {
        			        while (check.executeStep()) {
        			            exists = true;
    			            
        			            var update = sf_db.createStatement("UPDATE blog_templates SET template=?1, date=?2, live_preview=?3 WHERE blog_guid=?4");
        			            update.bindUTF8StringParameter(3, guid);
        			            update.bindUTF8StringParameter(0, select.getUTF8String(1));
        			            update.bindInt64Parameter(1, select.getInt64(2));
        			            update.bindInt32Parameter(2, select.getInt32(3));
    			            
        			            update.execute();
        			            update.finalize();
    			            
        			            break;
    			            }
    			        } catch (e) {
    		            } finally {
    		                check.reset();
    	                }
	                
    	                if (!exists) {
    	                    var insert = sf_db.createStatement("INSERT INTO blog_templates (blog_guid, template, date, live_preview) VALUES (?1, ?2, ?3, ?4)");
    			            insert.bindUTF8StringParameter(0, guid);
    			            insert.bindUTF8StringParameter(1, select.getUTF8String(1));
    			            insert.bindInt64Parameter(2, select.getInt64(2));
    			            insert.bindInt32Parameter(3, select.getInt32(3));
			            
    			            insert.execute();
    			            insert.finalize();
                        }
        			}
        		} catch (e) {
        		} finally {
        			select.reset();
        		}
        	} catch (e) {
        	    alert("Error importing blog templates:\n\n" + e);
        	}
            
            // Prefs
            try {
                var select = db.createStatement("SELECT name, type, value FROM prefs");

        		try {
        			while (select.executeStep()) {
        			    var name = select.getUTF8String(0);
                        var type = select.getUTF8String(1);
                        var value = select.getUTF8String(2);
                        
                        try {
                            switch (type) {
                                case 'bool':
                                    if (value == "true") {
                                        value = true;
                                    }
                                    else {
                                        value = false;
                                    }
                                    
                                    this.prefs.setBoolPref(name, value);
                                break;
                                case 'int':
                                    value = parseInt(value, 10);
                                    
                                    this.prefs.setIntPref(name, value);
                                break;
                                case 'string':
                                    var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
                        		    str.data = value;
                        		    this.prefs.setComplexValue(name, Components.interfaces.nsISupportsString, str);
                                break;
                            }
                        } catch (e) {
                        }
        			}
        		} catch (e) {
        		} finally {
        			select.reset();
        		}
        	} catch (e) {
        	    alert("Error importing preferences:\n\n" + e);
        	}
            
            alert("Done! For best results, close and re-open ScribeFire before continuing.");
            
            try { db.close(); } catch (e) { }
            try { sf_db.close(); } catch (e) { }
        }
    },

    execFunction : function (callback) {
		var win = getScribefireWindow();
		
		if (win) {
			callback(win);
		}
		else {
			alert("No ScribeFire window.");
			// @todo
		}
    }
};

var SCRIBEFIRE_BLOG = {
	serviceObject : null,
	_guid : null,
	
	password : "",
	
    findGUID : function () {
        var theGUID = SCRIBEFIRE_DB.prefs.getCharPref("settings.lastselected.blog");
		return theGUID;
    },
	
	get guid() {
		return this._guid;
	},
	
	set guid(guid) {
	    if (!guid || this._guid != guid) {
    		this._guid = guid;
		    
		    if (guid) {
        		try {
        			guid = this.setupServiceObject();
        		} catch (e) {
            		SCRIBEFIRE_DB.prefs.setCharPref("settings.lastselected.blog", "");
        			throw e;
        		}
        	}
    		
    		SCRIBEFIRE_DB.prefs.setCharPref("settings.lastselected.blog", guid);
    	}
	},
	
	getter : function (field) {
		var db = SCRIBEFIRE_DB.getDB();
		
		var select = db.createStatement("SELECT "+field+" FROM "+SCRIBEFIRE_DB.blogsTable+" WHERE guid=?1 LIMIT 1");
		select.bindStringParameter(0, this.guid);
		
		var rv = "";
		
		try {
			while (select.executeStep()) {
				rv = select.getUTF8String(0);
			}
		} catch (e) {
		} finally {
			select.reset();
		}
		
		SCRIBEFIRE_DB.closeDB(db);
		
		return rv;
	},
	
	setter : function (field, value) {
		var db = SCRIBEFIRE_DB.getDB();
		
		var update = db.createStatement("UPDATE "+SCRIBEFIRE_DB.blogsTable+" SET "+field+"=?1 WHERE guid=?2");
		update.bindUTF8StringParameter(0, value);
		update.bindStringParameter(1, this.guid);
		update.execute();
		update.finalize();
		
		SCRIBEFIRE_DB.closeDB(db);
	},
	
	get supportsTags() {
		if (!this.serviceObject) return false;
		
		if (typeof this.serviceObject.supportsTags != 'undefined') {
			return this.serviceObject.supportsTags;
		}
		
		return false;
	},
	
	get supportsPages() {
		if (!this.serviceObject) return false;
		
		if (typeof this.serviceObject.supportsPages != 'undefined') {
			return this.serviceObject.supportsPages;
		}
		
		return false;
	},
	
	get supportsDrafts() {
		if (!this.serviceObject) return false;
		
		if (typeof this.serviceObject.supportsDrafts != 'undefined') {
			return this.serviceObject.supportsDrafts;
		}
		
		return false;
	},
	
	get addCategories() {
		if (!this.serviceObject) return false;
		
		if (typeof this.serviceObject.addCategories != 'undefined') {
			return this.serviceObject.addCategories;
		}
		
		return false;
	},
	
	get createCategories() {
		if (!this.serviceObject) return false;
		
		if (typeof this.serviceObject.createCategories != 'undefined') {
			return this.serviceObject.createCategories;
		}
		
		return false;
	},
	
	get api() {
		return this.getter("api");
	},
	
	get type() {
		return this.getter("type");
	},
	
	get key() {
		return this.getter("key");
	},
	
	get blogId() {
		return this.getter("blogId");
	},
	
	get useBoolean() {
		return this.getter("useBoolean");
	},
	
	get username() {
		return this.getter("username");
	},
	
	get url() {
		return this.getter("url");
	},

	get name() {
		return this.getter("name");
	},
	
	get id() {
		var rv = this.getter("id");
		return parseInt(rv, 10);
	},
	
	get ftp_username() {
	    return this.getter("ftp_username");
	},
	
    get ftp_host() {
	    return this.getter("ftp_host");
	},
	
    get ftp_path() {
	    return this.getter("ftp_path");
	},
	
    get ftp_url_to_path() {
	    return this.getter("ftp_url_to_path");
	},
	
    get ftp_protocol() {
	    return this.getter("ftp_protocol");
	},
	
	set api(val) {
		this.setter("api", val);
	},
	
	set type(val) {
		this.setter("type", val);
	},
	
	set key(val) {
		this.setter("key", val);
	},
	
	set blogId(val) {
		this.setter("blogId", val);
	},
	
	set useBoolean(val) {
		this.setter("useBoolean", val);
	},
	
	set username(val) {
		this.setter("username", val);
	},
	
	set url(val) {
		this.setter("url", val);
	},
	
	set name(val) {
		this.setter("name", val);
	},
	
	set ftp_username(val) {
	    this.setter("ftp_username", val);
	},
    set ftp_host(val) {
	    this.setter("ftp_host", val);
	},
    set ftp_path(val) {
	    this.setter("ftp_path", val);
	},
    set ftp_url_to_path(val) {
	    this.setter("ftp_url_to_path", val);
	},
    set ftp_protocol(val) {
	    this.setter("ftp_protocol", val);
	},
	
	setupServiceObject : function () {
		var apiObject = null;
		var aService = this.type;

		// Determine the API type from either the blogtype value of the blogapi value.
		switch (aService) {
			case "atom":
				apiObject = new perFormancingAtomAPI();
				break;
			case "s_atom":
			case "blogger_com":
			case "atom_blogger":
			case "atom_blogger_cust":
				apiObject = new perFormancingBloggerAtomAPI();
				break;
			case "livejournal_com":
			case "blogger_cust":
			case "s_blogger":
			case "blogger":
				apiObject = new perFormancingBloggerAPI();
				break;
			case "wordpress_com":
			case "typepad_com":
			case "wordpress_cust":
			case "moveabletype_cust":
			case "s_mt":
			case "mt":
			case "drupal_cust":
			case "textpattern_cust":
				apiObject = new perFormancingMovableTypeAPI();
				break;
			case "metaweblog":
			case "metaweblog_cust":
			case "s_metaweblog":
			case "msnspaces_com":
			case "performancing_com":
			case "jeeran_com":
			case "splinder_com":
			case "xanga_com":
			case "roller_cust":
				apiObject = new performancingMetaweblogAPI();
				break;
			case "s_myspace":
			case "myspace_com":
			    alert("MySpace blogs are no longer supported by ScribeFire.");
			    throw "Unsupported blog type."
				break;
			case "s_tumblr":
			case "tumblr_com":
				apiObject = new performancingTumblrAPI();
				break;
			default:
				throw "Could not set up API object for blog of type " + aService;
				break;
		}
		
		var url = this.url;
		var username = this.username;
		
		var thePassword = gPerformancingUtil.goGetPassword(this.username, this.url);
		
		if (thePassword) {
			apiObject.doSetup();
			apiObject.init(this.type, this.key, this.api, this.blogId, null, this.username, thePassword, false);

			this.serviceObject = apiObject;
		}
		else {
			this.guid = "";
		}
		
		return this.guid;
	}
};